package com.website.common.util;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpStatus;
import org.apache.http.client.CookieStore;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.cookie.BasicClientCookie;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.*;

/**
 * 描述
 *
 * @param null
 * @return
 * @author zhangshuw
 * @date 2018/7/2
 */
public final class HttpUtil {

	private static final Logger logger = LoggerFactory.getLogger(HttpUtil.class);

	private static final RequestConfig requestConfig = RequestConfig.custom()
			.setConnectTimeout(1000 * 20)//设置连接超时时间，单位毫秒。
			.setConnectionRequestTimeout(1000 * 20)//设置从connect Manager获取Connection 超时时间，单位毫秒。
			.setSocketTimeout(1000 * 120)//请求获取数据的超时时间，单位毫秒。
			.build();

	private static final CookieStore cookieStore = new BasicCookieStore();
	private static final CloseableHttpClient httpClient = HttpClients.custom()
			.setMaxConnTotal(200)//最大连接数
			.setMaxConnPerRoute(100)//单个路由最大连接数
			.setDefaultRequestConfig(requestConfig)
			.setDefaultHeaders(Collections.singleton(new BasicHeader(HttpHeaders.CONNECTION, HTTP.CONN_CLOSE)))
			.setDefaultCookieStore(cookieStore)
			.build();
	/**
	 * 通过post获取数据
	 * @param url 请求地址
	 * @param map 请求参数
	 * @param chartset 默认为utf-8
	 * @return
	 * @throws IOException
	 */
	public static String post(String url, Map<String, String> map, String chartset) throws IOException{
		String result = "";
		CloseableHttpResponse resp = null;
		HttpPost httpPost = null;
		try{
			if(StringUtils.isBlank(chartset)){
				chartset = "utf-8";
			}
			httpPost = new HttpPost(url);
			List<BasicNameValuePair> list = new ArrayList<>();
			Iterator<String> iter = map.keySet().iterator();
			while (iter.hasNext()){
				String key = iter.next();
				String value = map.get(key);
				list.add(new BasicNameValuePair(key, value));
			}
			UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list, "utf-8");
			entity.setContentEncoding(chartset);
			entity.setContentType("application/x-www-form-urlencoded;charset=utf-8");
			httpPost.setEntity(entity);

			resp = httpClient.execute(httpPost);
			if(resp.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
				HttpEntity he = resp.getEntity();
				result = EntityUtils.toString(he, chartset);
			}
		}catch(IOException e){
			logger.error("post:{}>{}", url, e.getMessage());
			throw e;
		}finally {
			if(httpPost != null){
				httpPost.releaseConnection();
			}
			if(resp!=null){
				resp.close();
			}
		}
		return result;
	}
	public static String postWithCookie(String url, Map<String, String> map,
			String chartset, String jsession) throws IOException{
		BasicClientCookie cookie = new BasicClientCookie("JSESSIONID", jsession);
		String s = url.substring(url.toLowerCase().indexOf("http://") + "http://".length());
		String domain = s.substring(0, s.indexOf("/"));
		String path = s.substring(domain.length());
        cookie.setDomain(domain.substring(0, domain.indexOf(":")));
        cookie.setPath(path);
		cookieStore.addCookie(cookie);
		String res = post(url, map, chartset);
		cookieStore.clear();
		return res;
	}

	/**
	 * post json数据
	 * @author guobingbing
	 * @date 2017/7/14 11:20
	 * @param url, jsonData, chartset
	 * @param jsonData
	 * @return java.lang.String
	 * @throws Exception
	 */
	public static String postJSON(String url, String jsonData, String chartset) throws IOException{
		String result = null;
		HttpPost httpPost = null;
		CloseableHttpResponse response = null;
		try{
			if(StringUtils.isBlank(chartset)){
				chartset = "utf-8";
			}
			httpPost = new HttpPost(url);
			httpPost.addHeader(HTTP.CONTENT_TYPE, "application/json");
			StringEntity entity = new StringEntity(jsonData, chartset);
			entity.setContentEncoding(chartset);
			entity.setContentType("text/json");
			entity.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
			httpPost.setEntity(entity);
			response = httpClient.execute(httpPost);
			if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
				HttpEntity he = response.getEntity();
				result = EntityUtils.toString(he, chartset);
			}else{
				String body = EntityUtils.toString(response.getEntity(), chartset);
				logger.warn("statusLine:{},\r\nbody:{}", response.getStatusLine(),
						body.length() > 300 ? (body.substring(0, 300) + "...") : body);
			}
		}catch(IOException e){
			logger.error("postJSON:" + url + ">" + e.getMessage(), e);
			throw e;
		}finally {
			if(response!=null){
				response.close();
			}
			if(httpPost!=null){
				httpPost.releaseConnection();
			}
		}
		return result;
	}

	/**
	 * get请求
	 * @param url
	 * @param map
	 * @param chartset
	 * @return
	 * @throws IOException
	 */
	public static String get(String url, Map<String, String> map, String chartset) throws IOException{
		String result = "";
		HttpGet httpGet = null;
		CloseableHttpResponse response = null;
		try{
			if(StringUtils.isBlank(chartset)){
				chartset = "utf-8";
			}
			List<BasicNameValuePair> list = new ArrayList<>();
			if(map!=null && !map.isEmpty()) {
				Iterator<String> iter = map.keySet().iterator();
				while (iter.hasNext()) {
					String key = iter.next();
					String value = map.get(key);
					list.add(new BasicNameValuePair(key, value));
				}
			}
			String params = EntityUtils.toString(new UrlEncodedFormEntity(list, chartset));
			httpGet = new HttpGet(url + "?" + params);
			response = httpClient.execute(httpGet);
			HttpEntity he = response.getEntity();
			result = EntityUtils.toString(he, chartset);

		}catch(IOException e){
			logger.error("get:{}>{}", url, e.getMessage());
			throw e;
		}finally {
			if(response!=null){
				response.close();
			}
			if(httpGet!=null){
				httpGet.releaseConnection();
			}
		}
		return result;
	}

	/**
	 * put请求
	 * @param url
	 * @param json
	 * @param headers
	 * @param chartset
	 * @return
	 * @throws Exception
	 */
	public static String put(String url, String json, Map<String,String> headers, String chartset) throws Exception{
		String result = "";
		HttpPut httpPut = null;
		CloseableHttpResponse response = null;
		try{
			if(StringUtils.isBlank(chartset)){
				chartset = "utf-8";
			}
			httpPut = new HttpPut(url);
			httpPut.setHeader(HTTP.CONTENT_TYPE, "application/json");
			if(headers!=null && headers.size()>0){
				for (Map.Entry<String, String> entity : headers.entrySet()){
					httpPut.setHeader(entity.getKey(), entity.getValue());
				}
			}
			StringEntity stringEntity = new StringEntity(json, chartset);
			httpPut.setEntity(stringEntity);
			response = httpClient.execute(httpPut);
			HttpEntity entity = response.getEntity();
			result = EntityUtils.toString(entity, chartset);
		}catch(IOException e){
			logger.error("put:{}>{}", url, e.getMessage());
			throw e;
		}finally {
			if(response!=null){
				response.close();
			}
			if(httpPut!=null){
				httpPut.releaseConnection();
			}
		}
		return result;
	}

	/**
	 * 关闭客户端
	 * 系统关闭前调用，调用此方法后。请求将不能发出
	 * @author  zhanshuw
	 * 			2018年1月23日
	 */
	public static void closeClient(){
		try {
			httpClient.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
